package cn.zb.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
@EnableWebSecurity // 开启security功能
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    MyUserDetailsService detailsService; // 用户登录授权配置类
    @Resource
    AuthException authException; // 认证异常类
    @Resource
    LogoutHandler logoutHandler; // 注销配置
    @Resource
    LogoutSuccessHandler logoutSuccessHandler; // 注销成功配置
    @Resource
    TokenFilter tokenFilter; // 从请求头解析用户对象
    @Resource
    AccessException accessException;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**").permitAll();

        http.csrf().disable();
        // 配置获取用户信息方式
        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
        // 认证异常
        http.exceptionHandling().authenticationEntryPoint(authException);
        // 鉴权异常
        http.exceptionHandling().accessDeniedHandler(accessException);
        // 配置注销
        http.logout().logoutUrl("/logout")
                .addLogoutHandler(logoutHandler)
                .logoutSuccessHandler(logoutSuccessHandler);
        // 允许跨域
        http.cors();
    }

    // 配置认证方式+加密方式

    /**
     * auth.inMemoryAuthentication() 内存认证 自定义账号密码 需要指定加密方式
     * auth.userDetailsService() 查询数据库用户详情方式认证
     * auth.AuthenticationProvider() 身份认证方式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(dap());
    }

    @Bean
    public DaoAuthenticationProvider dap() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(pe());
        provider.setUserDetailsService(detailsService);
        provider.setHideUserNotFoundExceptions(false);
        return provider;
    }

    @Bean
    public PasswordEncoder pe(){
        // BCryptPasswordEncoder SHA256+随机盐
        return new BCryptPasswordEncoder();
    }

    // 用来登录认证的对象
    @Bean
    public AuthenticationManager am() throws Exception {
        return authenticationManagerBean();
    }
}
